package com.hc.smartcall;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;
import java.security.Security;

public class SM4EncryptionExample {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Test
    public void testMain() throws Exception {
        // 生成密钥
        byte[] key = generateKey();

        // 初始化向量
        byte[] iv = new byte[16];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);

        // 待加密的明文
        String plainText = "admin123!";
        byte[] plainBytes = plainText.getBytes();

        // 加密
        byte[] encryptedBytes = encrypt(key, iv, plainBytes);
        System.out.println("Encrypted: " + Hex.toHexString(encryptedBytes));

        // 解密
        byte[] decryptedBytes = decrypt(key, iv, encryptedBytes);
        System.out.println("Decrypted: " + new String(decryptedBytes));
    }

    public static byte[] generateKey() throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance("SM4", "BC");
        kg.init(128, new SecureRandom());
        SecretKey sk = kg.generateKey();
        return sk.getEncoded();
    }

    public static byte[] encrypt(byte[] key, byte[] iv, byte[] plainBytes) throws Exception {
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
        cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv));
        byte[] output = new byte[cipher.getOutputSize(plainBytes.length)];
        int length = cipher.processBytes(plainBytes, 0, plainBytes.length, output, 0);
        cipher.doFinal(output, length);
        return output;
    }

    public static byte[] decrypt(byte[] key, byte[] iv, byte[] encryptedBytes) throws Exception {
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
        cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
        byte[] output = new byte[cipher.getOutputSize(encryptedBytes.length)];
        int length = cipher.processBytes(encryptedBytes, 0, encryptedBytes.length, output, 0);
        cipher.doFinal(output, length);
        return output;
    }
}    